﻿using ComponentFactory.Krypton.Toolkit;
using StableDiffusionTools.Enums;
using StableDiffusionTools.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace StableDiffusionTools.Themes
{
    public static class GlobalTheme
    {
        const string themeManifestPath = "StableDiffusionTools.Themes.";
        const string themeManifestExt = ".xml";

        static readonly PaletteModeManager[] managerThemes = { PaletteModeManager.Office2010Blue, PaletteModeManager.Office2010Silver };
        static readonly object locker = new object();
        static bool init;

        static KryptonPalette kryptonPalette;
        static KryptonManager kryptonManager;
        private static KryptonManager GetKryptonManager()
        {
            if (kryptonManager == null)
                kryptonManager = new KryptonManager();

            return kryptonManager;
        }

        static Theme currentTheme = Theme.Invalid;
        static List<string> themeFiles = new List<string>();
        static string lastThemeFile;

        public static Theme ActiveTheme
        {
            get => currentTheme;
            set => LoadTheme(value);
        }

        public static void Init()
        {
            lock (locker)
            {
                if (!init)
                {
                    init = true;
                    Assembly assembly = GetAssembly();
                    LoadThemeFilesFromManifest(assembly);
                    LoadTheme(GlobalSettingsManager.GetSettings().CurrentTheme, assembly);
                }
            }
        }

        public static void LoadTheme(Theme theme, Assembly assembly = null)
        {
            if (theme != currentTheme)
            {
                currentTheme = theme;
                string themeName = EnumUtil.GetName(theme);
                if (TryLoadFromManifestFile(themeName, assembly) || TryLoadFromPalettleModeManager(themeName))
                {
                    var globalSettings = GlobalSettingsManager.GetSettings();
                    globalSettings.CurrentTheme = theme;
                    GlobalSettingsManager.SaveSettings();
                }
            }
        }

        private static void LoadThemeFilesFromManifest(Assembly assembly)
        {
            var names = assembly.GetManifestResourceNames();
            for (int i = 0; i < names.Length; i++)
            {
                string name = names[i];
                if (name.StartsWith(themeManifestPath) && name.EndsWith(themeManifestExt))
                {
                    themeFiles.Add(name);
                }
            }
        }

        private static bool TryLoadFromPalettleModeManager(string theme)
        {
            for (int i = 0; i < managerThemes.Length; i++)
            {
                if (EnumUtil.GetName(managerThemes[i]).EndsWith(theme))
                {
                    GetKryptonManager().GlobalPaletteMode = managerThemes[i];
                    return true;
                }
            }
            return false;
        }

        private static bool TryLoadFromManifestFile(string theme, Assembly assembly = null)
        {
            Assembly a = assembly ?? GetAssembly();
            KryptonPalette palette = null;
            for (int i = 0; i < themeFiles.Count; i++)
            {
                string themeName = themeFiles[i].Substring(themeManifestPath.Length, themeFiles[i].Length - (themeManifestPath.Length + themeManifestExt.Length));
                if (themeName.Equals(theme, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (!themeFiles[i].Equals(lastThemeFile) || kryptonPalette == null)
                    {
                        palette = new KryptonPalette();
                        lastThemeFile = themeFiles[i];
                        palette.Import(a.GetManifestResourceStream(lastThemeFile));
                        kryptonPalette = palette;
                    }
                    GetKryptonManager().GlobalPalette = kryptonPalette;
                    return true;
                }
            }
            return false;
        }

        private static Assembly GetAssembly() => Assembly.GetAssembly(typeof(GlobalTheme));
    }
}